package netty.discard;

/**
 * @Description: DiscardServer
 * @Author: zhongyuan
 * @CreateDate: 2020/8/25
 */
import io.netty.buffer.ByteBuf;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;

/**
 * Handles a server-side channel.
 */
public class DiscardServerHandler extends ChannelInboundHandlerAdapter {
    /*
        (1) DiscardServerHandler extends ChannelInboundHandlerAdapter, which is an implementation of ChannelInboundHandler.
        ChannelInboundHandler provides various event handler methods that you can override. For now, it is just enough to
        extend ChannelInboundHandlerAdapter rather than to implement the handler interface by yourself.
     */

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf in = (ByteBuf) msg;

        //case 3 ----------------------------------------------------------------
        ctx.write(msg);
        /*
         (1) A ChannelHandlerContext object provides various operations that enable you to trigger various I/O events and
         operations. Here, we invoke write(Object) to write the received message in verbatim. Please note that we did not
         release the received message unlike we did in the DISCARD example. It is because Netty releases it for you when
         it is written out to the wire.
         */
        ctx.flush();
        /*
         (2) ctx.write(Object) does not make the message written out to the wire. It is buffered internally and then flushed
         out to the wire by ctx.flush(). Alternatively, you could call ctx.writeAndFlush(msg) for brevity.
         */
        //case 3 end-------------------------------------------------------------


        //case 2-------------------------------------------------------------
        try {
            while (in.isReadable()) {
                /*
                 (1) This inefficient loop can actually be simplified to: System.out.println(in.toString(io.netty.util.CharsetUtil.US_ASCII))
                 */
                System.out.print((char) in.readByte());
                System.out.flush();
            }
        } finally {
            ReferenceCountUtil.release(msg); // (2)Alternatively, you could do in.release() here.
        }
        //case 2 end-------------------------------------------------------------


        /*
         (2) We override the channelRead() event handler method here. This method is called with the received message,
         whenever new data is received from a client. In this example, the type of the received message is ByteBuf.
         */
        // Discard the received data silently.
       // ((ByteBuf) msg).release();
        /*
         (3) To implement the DISCARD protocol, the handler has to ignore the received message. ByteBuf is a reference-counted
         object which has to be released explicitly via the release() method. Please keep in mind that it is the handler's
         responsibility to release any reference-counted object passed to the handler. Usually, channelRead() handler method
         is implemented like the following:
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) {
                try {
                    // Do something with msg
                } finally {
                    ReferenceCountUtil.release(msg);
                }
            }
         */
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        /*
         (4) The exceptionCaught() event handler method is called with a Throwable when an exception was raised by Netty
         due to an I/O error or by a handler implementation due to the exception thrown while processing events. In most
         cases, the caught exception should be logged and its associated channel should be closed here, although the
         implementation of this method can be different depending on what you want to do to deal with an exceptional
         situation. For example, you might want to send a response message with an error code before closing the connection.
         */
        // Close the connection when an exception is raised.
        cause.printStackTrace();
        ctx.close();
    }
}